package guda.talk.web.common;

/**
 * Created by well on 15/3/16.
 */

import com.alibaba.citrus.service.uribroker.URIBrokerService;
import com.alibaba.citrus.service.uribroker.uri.URIBroker;
import com.alibaba.citrus.springext.support.BeanSupport;
import com.alibaba.citrus.turbine.TurbineRunData;
import com.alibaba.citrus.turbine.pipeline.valve.PageAuthorizationValve.Callback;
import com.alibaba.citrus.webx.util.WebxUtil;
import com.alibaba.fastjson.JSON;

import guda.talk.biz.beans.JsonResult;
import guda.talk.biz.common.auth.AuthUser;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;


public class DefaultAuth extends BeanSupport implements Callback<DefaultAuth.Status> {
    private static final Logger log = LoggerFactory.getLogger(DefaultAuth.class);


    @Autowired
    private URIBrokerService uriBrokerService;

    public static final  String sessionKey = "J_TALK_KEY";



    public void init() {

    }

    public Status onStart(TurbineRunData rundata) {
        HttpSession session = rundata.getRequest().getSession();
        AuthUser user = null;

        try {
            user = (AuthUser) session.getAttribute(sessionKey);
        } catch (Exception e) {
            log.warn("Failed to read admin from session: " + sessionKey, e);
        }

        if (user == null) {
            // 创建匿名用户
            user = new AuthUser();
            session.setAttribute(sessionKey, user);
            AuthUser.cleanThreadLocal();
        }

        // 将user设置到rundata中，以便其它程序使用。
        AuthUser.setCurrentUser(user);

        return new Status(rundata, user);
    }

    public String getUserName(Status status) {
        if (status.user.getUserId() == null) {
            return "anonymous";
        }
        return status.user.getUserId().toString();
    }


    public String[] getRoleNames(Status status) {
        return status.user.getRoles();
    }

    public String[] getActions(Status status) {
        return null;
    }

    public void onAllow(Status status) throws Exception {
    }

    public void onDeny(Status status) throws Exception {
        if (status.rundata.getTarget().endsWith(".json")) {
            response401(status.rundata.getResponse());
            return;
        }
        String name = WebxUtil.getCurrentComponent(status.rundata.getRequest()).getName();
        HttpServletRequest request = status.rundata.getRequest();
        String redirectUrl = buildRedirectUrl(request);
        if ("home".equals(name)) {
            URIBroker redirectURI = uriBrokerService.getURIBroker("homeLoginLink");
            status.rundata.getResponse().sendRedirect(redirectURI.addQueryData("redirectURL", redirectUrl).render());
        }
    }

    private String buildRedirectUrl(HttpServletRequest request) {
        if (request == null) {
            return "";
        }
        StringBuffer targetUrl = request.getRequestURL();
        String queryString = request.getQueryString();
        if (StringUtils.isBlank(queryString)) {
            return targetUrl.toString();
        }
        return targetUrl.append("?").append(queryString).toString();
    }

    private void response401(HttpServletResponse response) {
        response.addHeader("Cache-Control", "no-cache");
        response.setContentType("application/json");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            JsonResult jsonResult = new JsonResult();
            jsonResult.setErrMsg("未授权");
            out.write(JSON.toJSONString(jsonResult.getMap()));
        } catch (Exception e) {
            log.error("", e);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    static class Status {
        private final TurbineRunData rundata;
        private AuthUser user;

        public Status(TurbineRunData rundata, AuthUser user) {
            this.rundata = rundata;
            this.user = user;
        }
    }
}